/*
 * AutoTagger.java
 *
 * Created on July 3, 2007, 1:48 PM
 *
 * To change this template, choose Tools | Template Manager
 * and open the template in the editor.
 */

package com.semanticvoid.lifelogger.autotag;

import com.semanticvoid.lifelogger.db.DbInterface;
import com.semanticvoid.lifelogger.entity.TagEntity;
import com.semanticvoid.lifelogger.entity.TaggedBrowseHistoryEntity;
import com.semanticvoid.lifelogger.http.ContentFetcher;
import java.util.Arrays;
import java.util.Calendar;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.TimeZone;
import java.util.Vector;

/**
 *
 * @author anand_kishore
 */
public class AutoTagger {
    
    /** Term Vector */
    private Map<String, Integer> universalTermVector;
    
    /** Tag Entities */
    private Map<String, TagEntity> tagEntities;
    
    /** URL Queue */
    private List<String> URLQueue = Collections.synchronizedList(new LinkedList<String>());
    
    /** Total number of documents */
    private int totalNumberOfEntities;
    
    /** Creates a new instance of AutoTagger */
    public AutoTagger() {
        universalTermVector = new HashMap<String, Integer>();
        tagEntities = new HashMap<String, TagEntity>();
                
        init();
    }
    
    private void init() {
        Set<String> tags = DbInterface.getAllTagsInTheSystem();
        totalNumberOfEntities = DbInterface.getNumberOfTaggedEntitiesInTheSystem();
        
        Iterator itr = tags.iterator();
        while(itr.hasNext()) {
            String tag = (String) itr.next();
            
            TagEntity tEntity = new TagEntity(tag);
            tEntity.formTermVector();
            
            tagEntities.put(tag, tEntity);
            
            // Form the universal term vector
            
            Map<String, Integer> localTermVector = tEntity.getTermVector();
            Set<String> localKeys = localTermVector.keySet();
            Iterator itr_local = localKeys.iterator();
            
            while(itr_local.hasNext()) {
                String token = (String) itr_local.next();
                int local_count = localTermVector.get(token);
                
                if(universalTermVector.containsKey(token)) {
                    int count = universalTermVector.get(token);
                    count = count + local_count;
                    universalTermVector.put(token, count);
                } else {
                    universalTermVector.put(token, local_count);
                }
            }
            
        }
    }
    
    public void start() {
        
        // Start URL fetcher thread
//        new Thread() {
//            public void run() {
//                fetchURLs();
//            }
//        }.start();
        
        // Start comparator thread
        new Thread() {
            public void run() {
                performComparison();
                System.exit(1);
            }
        }.start();
    }
    
    private void fetchURLs() {
        
    }
    
    private void performComparison() {
        String link = null;
        
        if(URLQueue.size() > 0) {
            link = URLQueue.get(0);
            
            String content = ContentFetcher.fetch(link);
            
            TaggedBrowseHistoryEntity tEntity = new TaggedBrowseHistoryEntity(String.valueOf(link.hashCode()), link, Calendar.getInstance(TimeZone.getTimeZone("GMT")), null, null, (short) -1, null, content);
            
            if(compare(tEntity)) {
                System.out.println(tEntity.toString());
            }
        }
    }
    
    public boolean compare(TaggedBrowseHistoryEntity tEntity) {
        Map<String, Integer> entityTermVector = tEntity.extractTermVectorAsMap();
        Vector<TagProbability> tagProbabilities = new Vector<TagProbability>();
        
        Set<String> tags = tagEntities.keySet();
        Iterator itr_tags = tags.iterator();
        while(itr_tags.hasNext()) {
            String tag = (String) itr_tags.next();
            TagEntity tagEntity = tagEntities.get(tag);
            
            Map<String, Integer> tagTermVector = tagEntity.getTermVector();
            
            double likelihood = calculateProbability(entityTermVector, tagTermVector);
            double prior = (double) tagEntity.getNumberOfEntities() / (double) totalNumberOfEntities;
            double probability = likelihood * prior;
            
            TagProbability tagProb = new TagProbability(tag, probability);
            tagProbabilities.add(tagProb);
        }
        
        Collections.sort(tagProbabilities);
        
        for(TagProbability tp : tagProbabilities) {
            System.out.println(tp.getProbability() + " " + tp.getTag());
        }
        
        return true;
    }
    
    private double calculateProbability(Map<String, Integer> t1, Map<String, Integer> t2) {
        int totalNumberOfWordsInT2 = 0;
        double likelihood = 0;
        
        // Calculate total number of words in t2
        Collection<Integer> t2_values = t2.values();
        Iterator t2_values_itr = t2_values.iterator();
        while(t2_values_itr.hasNext()) {
            int temp = (Integer) t2_values_itr.next();
            totalNumberOfWordsInT2 += temp;
        }
        
        // Calculate probablities for individual words
        Set<String> t1_keys = t1.keySet();
        Iterator t1_keys_itr = t1_keys.iterator();
        while(t1_keys_itr.hasNext()) {
            String token = (String) t1_keys_itr.next();
            
            if(t2.containsKey(token)) {
                int freq = t2.get(token);
                
                double tokenProbability = (double) freq / (double) totalNumberOfWordsInT2;
                
                likelihood += tokenProbability;
            }
        }
        
        return likelihood;
    }

    class TagProbability implements Comparable {
        private String tag;
        private double probability;
        
        public TagProbability(String tag, double probability) {
            this.tag = tag;
            this.probability = probability;
        }

        public String getTag() {
            return tag;
        }

        public void setTag(String tag) {
            this.tag = tag;
        }

        public double getProbability() {
            return probability;
        }

        public void setProbability(double probability) {
            this.probability = probability;
        }

        public int compareTo(Object o) {
            double p1 = this.getProbability();
            TagProbability temp = (TagProbability) o;
            double p2 = temp.getProbability();
            
            if(p1 > p2) {
                return -1;
            } else if(p1 < p2) {
                return 1; 
            } else {
                return 0;
            }
        }
    }
}
